/********************************************************************************
TITLE:                      	Using Virtual Functions
FILENAME:                   	mediacollection.cpp
PREPARED FOR:               	CS215 Section CS13-02
PROGRAMMER(S):              	Eric (Fox) Crowell, Timothy Drye
DEVELOPMENT DATE:           	< 12/15/13 >
COMPILER USED:      			Microsoft Visual Studio Professional 2013
- Version 12.0.21005.1 REL
TARGET PLATFORM:         	    Windows 8 x64
================================================================================
REVISION HISTORY

DATE         PROGRAMMER          DESCRIPTION OF CHANGES MADE
------------------------------------------------------------------------------
<12/15/13       Fox                 Class Created.                           >
<12/19/13       Fox                 Completed implementing member functions. >
*******************************************************************************/

#include "mediacollection.h"

// Default constructor. [Fox]
MediaCollection::MediaCollection() {
	CurrentMCSize = 0;
	cout << "\n              Your Media Collection\n";
	cout << "##################################################\n";
	cout << "Please input the name of your Media Collection...\n";
	cout << "Name: ";
	cin >> CollectionName;
	cout << "\n";

	// Start each pointer as NULL.
	for (int i = 0; i < MediaCollectionSize; i++){
		Collection[i] = NULL;
	}
}

// Destructor. [Fox]
MediaCollection::~MediaCollection() {
	// Delete all non-null pointers in the array. [Fox]
	// There should be NO chance for memory leaks with the way I set this up. [Fox]
	// See DeleteMedia() for more details.
	for (int i = 0; i < MediaCollectionSize; i++){
		if (Collection[i] != NULL){
			delete Collection[i];
		}
	}
}

// Adds a media object to the class. [Fox]
void MediaCollection::AddMedia() {
	MediaType Selection;

	if (CurrentMCSize < MediaCollectionSize){
		DisplayMediaTypeMenu();
		Selection = GetMediaTypeSelection();
		switch (Selection){
		case (MediaType::AUDIO_CASSETTE) :
			Collection[CurrentMCSize] = new AudioCassette;
			break;
		case (MediaType::AUDIO_CD) :
			Collection[CurrentMCSize] = new AudioCD;
			break;
		case (MediaType::VIDEO_VHS) :
			Collection[CurrentMCSize] = new VideoVHS;
			break;
		case (MediaType::VIDEO_DVD) :
			Collection[CurrentMCSize] = new VideoDVD;
			break;
		}
		assert(Collection[CurrentMCSize]);
		CurrentMCSize++;
		cout << "   [i] New media item created successfully.\n";
	} else {
		// Display a message telling the user the collection is full. [Fox]
		cout << "   [!] Media collection is full (Maxed at " << MediaCollectionSize << " items).\n";
	}
	cout << "   --------------------------------------------------\n\n";
}

// Removes a media type from the class. [Fox]
void MediaCollection::DeleteMedia() {
	cout << "   --------------------------------------------------\n";
	cout << "   DELETE MEDIA ITEM \n";
	cout << "   --------------------------------------------------\n";
	// Print each existing media item. [Fox]
	int i = 0, selection = 0;
	for (i = 0; i < CurrentMCSize; i++){
		cout << "   " << (i + 1) << ") " << Collection[i]->GetTitle() << "\n";
	}
	i++; // Easier than continuing to use (i + 1). [Fox]
	// Allow the user to cancel. [Fox]
	cout << "   " << i << ") Cancel";
	// Wait for correct input. [Fox]
	while (selection < 1 || selection > i ){
		// Clean the cin stream. [Fox]
		cin.clear();
		cin.ignore(cin.rdbuf()->in_avail());
		// Ask for input. [Fox]
		cout << "\n   Selection (1-" << i << "): ";
		cin >> selection;
	}
	// If the selection is last in the list, cancel the operation. [Fox]
	if (selection == i){
		cout << "   [i] Canceled.\n";
	// Otherwise, delete the item in the media. [Fox]
	} else {
		// Fill in the gap of the deleted media item. [Fox]
		int j = (selection - 1);
		// Delete the last item in the list. [Fox]
		delete Collection[j];
		for (j; j < (CurrentMCSize - 1); j++){
			Collection[j] = Collection[j + 1];
		}
		CurrentMCSize--; // Decrease CurrentMCSize by 1. [Fox]
		// Set the last element to NULL [Fox]
		Collection[CurrentMCSize] = NULL;
		cout << "   [i] Media item #" << selection << " deleted.\n";
	}
	cout << "   --------------------------------------------------\n\n";
}

// Plays the current song selection. [Fox]
void MediaCollection::PlaySelection() {
	cout << "   --------------------------------------------------\n";
	cout << "   PLAY MEDIA ITEM \n";
	cout << "   --------------------------------------------------\n";
	int i = 0;
	for (i; i < CurrentMCSize; i++){
		cout << "   " << (i + 1) << ") " << Collection[i]->GetTitle() << "\n";
	}
	int selection = 0;
	// Wait for correct input. [Fox]
	while (selection < 1 || selection > i){
		// Clean the cin stream. [Fox]
		cin.clear();
		cin.ignore(cin.rdbuf()->in_avail());
		// Ask for input. [Fox]
		cout << "\n   Selection (1-" << i << "): ";
		cin >> selection;
	}

	// Initiate the play function on the selected media.
	Collection[(selection-1)]->Play();

	cout << "   --------------------------------------------------\n\n";
}

// Fast forwards to the end of the song that is currently selected. [Fox]
// Asks what media to fast forward to.
// Fast forwards the media to the begining.
void MediaCollection::FastForward() {
	cout << "   --------------------------------------------------\n";
	cout << "   FAST FORWARD MEDIA ITEM \n";
	cout << "   --------------------------------------------------\n";
	int i = 0;
	for (i; i < CurrentMCSize; i++){
		cout << "   " << (i + 1) << ") " << Collection[i]->GetTitle() << "\n";
	}
	int selection = 0;
	// Wait for correct input. [Fox]
	while (selection < 1 || selection > i){
		// Clean the cin stream. [Fox]
		cin.clear();
		cin.ignore(cin.rdbuf()->in_avail());
		// Ask for input. [Fox]
		cout << "\n   Selection (1-" << i << "): ";
		cin >> selection;
	}

	// Initiate the play function on the selected media.
	Collection[(selection - 1)]->FastForward();

	cout << "   --------------------------------------------------\n\n";
}

// Rewinds to the begining of the songs selections. [Fox]
void MediaCollection::Rewind() {
	cout << "   --------------------------------------------------\n";
	cout << "   REWIND MEDIA ITEM \n";
	cout << "   --------------------------------------------------\n";
	int i = 0;
	for (i; i < CurrentMCSize; i++){
		cout << "   " << (i + 1) << ") " << Collection[i]->GetTitle() << "\n";
	}
	int selection = 0;
	// Wait for correct input. [Fox]
	while (selection < 1 || selection > i){
		// Clean the cin stream. [Fox]
		cin.clear();
		cin.ignore(cin.rdbuf()->in_avail());
		// Ask for input. [Fox]
		cout << "\n   Selection (1-" << i << "): ";
		cin >> selection;
	}

	// Initiate the play function on the selected media.
	Collection[(selection - 1)]->Rewind();

	cout << "   --------------------------------------------------\n\n";
}

// Prints the details of each media object included in this collection. [Fox]
void MediaCollection::PrintMediaDetails() {
	cout << "   Displaying all media details... \n\n";
	// Loop through each media item. [Fox]
	for (int i = 0; i < CurrentMCSize; i++){
		Collection[i]->PrintMedia(cout); // Print the details.
	}
	cout << "\n   Done. \n\n";
}

// Lists all the titles of the media objects included in this collection. [Fox]
void MediaCollection::ListMediaTitles() {
	cout << "   Displaying all media titles... \n\n";
	// Loop through each media item. [Fox]
	for (int i = 0; i < CurrentMCSize; i++){
		cout << "      " << Collection[i]->GetTitle() << "\n"; // Print the details.
	}
	cout << "   Done. \n\n";
}

// Return the total cost of every media item. [Fox]
float MediaCollection::CalculateMediaCollectionInvestment(){
	float sum = 0; // Declare the sum. [Fox]
	// Loop through each media item. [Fox]
	for (int i = 0; i < CurrentMCSize; i++){
		sum += Collection[i]->GetCost();
	}
	return(sum); // Return the total cost.
}

// Sum of all run-times for each song in each media object included in this collection. [Fox]
Time MediaCollection::CalculateTotalCollectionPlayingTime(){
	int hours = 0, minutes = 0;
	Time total(0, 0); // Declare Time object to store the total. [Fox]
	// Loop through each media item. [Fox]
	for (int i = 0; i < CurrentMCSize; i++){
		hours += Collection[i]->GetRunningTime().GetHours();
		minutes += Collection[i]->GetRunningTime().GetMinutes();
	}
	total.SetTime(hours, minutes);
	return(total); // Return the total time. [Fox]
}

// Gets the name of this collection. [Fox]
string MediaCollection::GetCollectionName(){
	return(CollectionName);
}

// Returns the total number of media objects in this collection. [Fox]
int MediaCollection::GetMCSize(){
	return(CurrentMCSize);
}

// Displays all the media types in this collection. [Fox]
void MediaCollection::DisplayMediaTypeMenu() {
	cout << "   --------------------------------------------------\n";
	cout << "   CREATE NEW MEDIA TYPE \n";
	cout << "   Current media items: " << CurrentMCSize << " of " << MediaCollectionSize << "\n";
	cout << "   --------------------------------------------------\n";
	cout << "   1) Audio Cassette\n";
	cout << "   2) Audio CD\n";
	cout << "   3) Video VHS\n";
	cout << "   4) Video DVD\n";
}

// Displays the current media object selected for playing music. [Fox]
MediaType MediaCollection::GetMediaTypeSelection(){
	int Selection = 0;
	
	// Loop until Selection is a valid number. [Fox]
	while (Selection < 1 || Selection > 4){
		// Clean the cin stream. [Fox]
		cin.clear();
		cin.ignore(cin.rdbuf()->in_avail());
		// Ask for input. [Fox]
		cout << "\n   Selection (1-4): ";
		cin >> Selection;

		switch (Selection){
		case 1: return(MediaType::AUDIO_CASSETTE); break;
		case 2: return(MediaType::AUDIO_CD); break;
		case 3: return(MediaType::VIDEO_VHS); break;
		case 4: return(MediaType::VIDEO_DVD); break;
		}
	}

	// Error that should never occur. [Fox]
	cout << "   [!] Error. Defaulting to Audio Cassette.";
	return(MediaType::AUDIO_CASSETTE);
}